﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;

namespace KinConquer.Packets.Handles
{
    public class NewHero
    {
        public unsafe static void Handle(Byte* Data, KinSocket.Connection Client)
        {
            Structures.NewHero* Packet = (Structures.NewHero*)Data;

            KinSocket.PacketConstructor.Dump(Data, true);

            if (Packet->Action == 0)
            {
                if (ValidName(Packet->CharacterName, true))
                {
                    if (!HeroExists(Packet->CharacterName))
                    {
                        if (ValidMesh(Packet->Mesh))
                        {
                            if (ValidClass(Packet->Job))
                            {
                                Random r = new Random((Int32)(KinSocket.Native.TIME.Now.Time + Client.Identifier));

                                UInt16 Hair = (UInt16)(r.Next(4, 9) * 100 + 10 + r.Next(4, 9));
                                UInt16 Avatar = (UInt16)((Packet->Mesh - 1000 >= 1000) ? r.Next(201, 250) : r.Next(1, 50));

                                UInt16 str = 0, vit = 0, spi = 0, agi = 0;
                                if (Entities.Hero.GetStats(Packet->Job, 1, ref str, ref vit, ref spi, ref agi))
                                {
                                    // Default items

                                    UInt32 hp = Entities.Calculations.HitPoints.HP(str, agi, spi, vit, Packet->Job);
                                    UInt32 mp = Entities.Calculations.HitPoints.MP(spi, Packet->Job);
                                    Program.Database.ExecuteNonQuery("INSERT INTO hero (id, name, transtype, avatar, body, hairstyle, " +
                                        "level, mapid, x, y, hitpoints, manapoints, firstclass, strength, agility, vitality, spirit, statpoints) VALUES (" +
                                        Client.Identifier + ", '" + Packet->CharacterName + "', 1, " + Avatar + ", " + Packet->Mesh + ", " +
                                        Hair + ", 1, 1010, 60, 109, " + hp + ", " + mp + ", " +
                                        Packet->Job + ", " + str + ", " + agi + ", " + vit + "," + spi + ", 0)");


                                    Client.Var |= KinSocket.Connection.VarTypes.BypassGameAuthCheck;
                                    Client.Send(Structures.MessageConst.ANSWER_OK_Dialog);
                                }
                                else Client.Send(new Structures.MessagePacket("Unable to get Hero stats.", "ALLUSERS", "SYSTEM", 0xffffff, Structures.MessagePacket.Types.Dialog));
                            }
                            else Client.Send(new Structures.MessagePacket("Invalid Hero Class.", "ALLUSERS", "SYSTEM", 0xffffff, Structures.MessagePacket.Types.Dialog));
                        }
                        else Client.Send(new Structures.MessagePacket("Invalid Body Selection.", "ALLUSERS", "SYSTEM", 0xffffff, Structures.MessagePacket.Types.Dialog));
                    }
                    else Client.Send(Structures.MessageConst.HeroExists);
                }
                else Client.Send(Structures.MessageConst.InvalidHeroName);
            }
            else
            {
                Program.GameConnections.Remove(Client.Identifier);
            }
        }

        public static bool ValidClass(UInt16 job)
        {
            if (job != 10 && job != 20 &&
                job != 40 && job != 50 &&
                job != 60 && job != 100)
                return false;
            return true;
        }

        public static bool ValidMesh(UInt16 mesh)
        {
            if (mesh != 1003 && mesh != 1004 &&
                mesh != 2001 && mesh != 2002)
                return false;
            return true;
        }

        public static bool HeroExists(string Name)
        {
            MySqlDataReader reader = null;
            Program.Database.ExecuteReader("SELECT id FROM hero WHERE name = '" + Name + "'", ref reader);
            if (reader != null)
            {
                if (!reader.Read())
                    return false;
            }
            return true;
        }

        public static bool ValidName(string CharacterName, bool AllowNumbers)
        {
            if (CharacterName.Contains('[') ||
                CharacterName.Contains(']'))
                return false;

            const byte NumStart = 48; // "0"
            const byte NumEnd = 57; // "9"
            const byte UpperStart = 65; // "A"
            const byte UpperEnd = 90; // "Z"
            const byte LowerStart = 97; // "a"
            const byte LowerEnd = 122; // "z"

            for (byte i = 0; i < CharacterName.Length; i++)
            {
                bool valid = false;
                byte c = (byte)CharacterName[i];
                if (AllowNumbers)
                {
                    if (c >= NumStart && c <= NumEnd)
                        valid = true;
                }
                if (c >= UpperStart && c <= UpperEnd)
                    valid = true;
                else if (c >= LowerStart && c <= LowerEnd)
                    valid = true;
                if (!valid)
                    return false;
            }
            return true;
        }
    }
}
